package com.xuecheng.manage_course.service;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.framework.domain.cms.response.CmsPageResult;
import com.xuecheng.framework.domain.cms.response.CmsPostPageResult;
import com.xuecheng.framework.domain.course.*;
import com.xuecheng.framework.domain.course.ext.CourseView;
import com.xuecheng.framework.domain.course.ext.TeachplanNode;
import com.xuecheng.framework.domain.course.request.CourseListRequest;
import com.xuecheng.framework.domain.course.response.CourseCode;
import com.xuecheng.framework.domain.course.response.CoursePublishResult;
import com.xuecheng.framework.domain.course.response.TeachplanMediaPub;
import com.xuecheng.framework.exception.ExceptionCast;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.framework.model.response.QueryResult;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.manage_course.client.CmsPageClient;
import com.xuecheng.manage_course.dao.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.transaction.Transactional;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Transactional
public class CourseService {

    @Autowired
    TeachplanMapper teachplanMapper;
    @Autowired
    TeachplanRepository teachplanRepository;
    @Autowired
    CourseBaseRepository courseBaseRepository;
    @Autowired
    CourseMapper courseMapper;
    @Autowired
    CourseMarketRepository courseMarketRepository;
    @Autowired
    CoursePicRepository coursePicRepository;
    @Autowired
    CoursePubRepository coursePubRepository;
    @Autowired
    private TeachplanMediaRepository teachplanMediaRepository;
    @Autowired
    TeachplanMediaPubRepository teachplanMediaPubRepository;

    @Value("${course-publish.dataUrlPre}")
    private String publish_dataUrlPre;
    @Value("${course-publish.pagePhysicalPath}")
    private String publish_page_physicalpath;
    @Value("${course-publish.pageWebPath}")
    private String publish_page_webpath;
    @Value("${course-publish.siteId}")
    private String publish_siteId;
    @Value("${course-publish.templateId}")
    private String publish_templateId;
    @Value("${course-publish.previewUrl}")
    private String previewUrl;

    /**
     * 获取课程计划节点
     * @param courseId
     * @return
     */
    public TeachplanNode findTeachplanList(String courseId) {
        return teachplanMapper.selectList(courseId);
    }

    //添加课程计划
    public ResponseResult addTeachplan(Teachplan teachplan) {
        //取出 courseid 和 parentid
        String courseid = teachplan.getCourseid();
        String parentid = teachplan.getParentid();
        if (StringUtils.isEmpty(courseid) && StringUtils.isEmpty(parentid)) {
            ExceptionCast.cast(CommonCode.INVALID_PARAMS);
        }
        if (!StringUtils.isEmpty(parentid)) {
            //用户勾选了 parentid, 直接存入数据库
            //给teachplan主键赋值
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            teachplan.setId(uuid);
            teachplan.setGrade("3"); // 小章节
            teachplanRepository.save(teachplan);
            return  new ResponseResult(CommonCode.SUCCESS);
        }

        //未勾选parentid, 根据courseid获取Teachplan根节点
        Teachplan rootTeachplan = teachplanRepository.findByCourseidAndGrade(courseid, "1");
        if (rootTeachplan != null) {
            teachplan.setParentid(rootTeachplan.getId());
            teachplan.setGrade("2"); //大章节
            teachplanRepository.save(teachplan);
            return  new ResponseResult(CommonCode.SUCCESS);
        }

        //Teachplan表中没有查询到根节点
        //查询course_base表, 获取课程信息
        Optional<CourseBase> courseBaseOptional = courseBaseRepository.findById(courseid);
        if (!courseBaseOptional.isPresent()) {
            ExceptionCast.cast(CommonCode.FAIL);
        }
        CourseBase courseBase = courseBaseOptional.get();
        //将该课程作为根节点添加到课程计划表中
        Teachplan newRootTeachplan = new Teachplan();
        newRootTeachplan.setParentid("0");
        newRootTeachplan.setPname(courseBase.getName());
        newRootTeachplan.setGrade("1");
        newRootTeachplan.setDescription(courseBase.getDescription());
        newRootTeachplan.setCourseid(courseBase.getId());
        //应该查一下teachplan表中一级节点的数量, 然后确定orderby数值
        newRootTeachplan.setOrderby(1);
        newRootTeachplan.setStatus("0");
        teachplanRepository.save(newRootTeachplan);
        //将前台传过来的teachplan中的parentid字段设置为新存入的根节点课程计划的id
        teachplan.setParentid(newRootTeachplan.getId());
        teachplanRepository.save(teachplan);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    /**
     * 查询课程列表
     * @param page
     * @param size
     * @param courseListRequest
     * @return
     */
    public QueryResponseResult findCourseList(int page, int size, CourseListRequest courseListRequest) {

        if (courseListRequest == null) {
            courseListRequest = new CourseListRequest();
        }
        //courseListRequest.setCompanyId("1");

        PageHelper.startPage(page, size);
        Page<CourseBase> courseBases = (Page) courseMapper.findAll(courseListRequest);
        for (CourseBase c: courseBases) {
            //设置每一个coursebase的pic属性
            Optional<CoursePic> coursePicOptional = coursePicRepository.findById(c.getId());
            if (coursePicOptional.isPresent()) {
                c.setPic(coursePicOptional.get().getPic());
            }
        }
        //封装QueryResult对象
        QueryResult<CourseBase> courseBaseQueryResult = new QueryResult<CourseBase>();
        courseBaseQueryResult.setList(courseBases);
        courseBaseQueryResult.setTotal(courseBases.getTotal());
        return new QueryResponseResult(CommonCode.SUCCESS, courseBaseQueryResult);
    }

    /**
     *   新增/修改  课程
     * @param courseBase
     * @return
     */
    public ResponseResult addCourse(CourseBase courseBase) {
        //String id = UUID.randomUUID().toString().replaceAll("-", "");
       // courseBase.setId(id);
        courseBaseRepository.save(courseBase);
        return new ResponseResult(CommonCode.SUCCESS);
    }



    /**
     * 根据id查询courseid
     * @param courseid
     * @return
     */
    public CourseBase findById(String courseid) {
        Optional<CourseBase> courseBaseOptional = courseBaseRepository.findById(courseid);
        if (courseBaseOptional.isPresent()) {
            return courseBaseOptional.get();
        }
        ExceptionCast.cast(CommonCode.SERVER_ERROR);
        return null;
    }

    /**
     * 根据courseId查询courseMarket信息
     * @param courseId
     * @return
     */
    public CourseMarket findCourseMarketByCourseId(String courseId) {
        Optional<CourseMarket> byId = courseMarketRepository.findById(courseId);
        if (byId.isPresent()) {
            return byId.get();
        }
        //ExceptionCast.cast(CommonCode.SERVER_ERROR);
        return null;
    }

    /**
     * 修改课程营销信息
     * @param courseid
     * @param courseMarket
     * @return
     */
    public ResponseResult updateCourseMarket(String courseid, CourseMarket courseMarket) {
        courseMarketRepository.save(courseMarket);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    /**
     * 查询课程视图
     * @param courseId
     * @return 课程视图  静态化数据模型
     */
    public CourseView getCourseView(String courseId) {
        CourseView courseView = new CourseView();
        //课程基本信息
        CourseBase courseBase = this.findById(courseId);
        courseView.setCourseBase(courseBase);
        //查询课程营销信息
        CourseMarket courseMarket = this.findCourseMarketByCourseId(courseId);
        courseView.setCourseMarket(courseMarket);
        //查询课程图片信息
        Optional<CoursePic> coursePicOptional = coursePicRepository.findById(courseId);
        if (coursePicOptional.isPresent()) {
            courseView.setCoursePic(coursePicOptional.get());
        }
        //查询课程计划
        TeachplanNode teachplanNode = teachplanMapper.selectList(courseId);
        courseView.setTeachplanNode(teachplanNode);
        return courseView;
    }

    //根据id查询课程基本信息
    public CourseBase findCourseBaseById(String courseId){
        Optional<CourseBase> baseOptional = courseBaseRepository.findById(courseId);
        if(baseOptional.isPresent()){
            CourseBase courseBase = baseOptional.get();
            return courseBase;
        }
        ExceptionCast.cast(CourseCode.COURSE_GET_NOTEXISTS);
        return null;
    }

    @Autowired
    CmsPageClient cmsPageClient;
    /**
     * 课程预览
     * @param courseId
     * @return
     */
    public CoursePublishResult preview(String courseId) {
       /* CourseBase one = this.findCourseBaseById(courseId);
        //1. 添加cmspage，获取pageId
        //发布课程预览页面
        CmsPage cmsPage = new CmsPage();
        //站点
        cmsPage.setSiteId(publish_siteId);//课程预览站点
        //模板
        cmsPage.setTemplateId(publish_templateId);
        //页面名称
        cmsPage.setPageName(courseId + ".html");
        //页面别名
        cmsPage.setPageAliase(one.getName());
        //页面访问路径
        cmsPage.setPageWebPath(publish_page_webpath);
        //页面存储路径
        cmsPage.setPagePhysicalPath(publish_page_physicalpath);
        //数据url
        cmsPage.setDataUrl(publish_dataUrlPre + courseId);*/

        // 1. 封装cmsPage对象，用于保存到cms_page表中
        CmsPage cmsPage = this.getCmsPage(courseId);
        //远程请求cms保存页面信息
        CmsPageResult cmsPageResult = cmsPageClient.save(cmsPage);
        //2. 拼装预览url，返回前端
        if (!cmsPageResult.isSuccess()) {
            return new CoursePublishResult(CommonCode.FAIL, null);
        }
        //页面id
        String pageId = cmsPageResult.getCmsPage().getPageId();
        //页面url
        String previewUrl = "http://www.xuecheng.com/cms/preview/" + pageId;
        return new CoursePublishResult(CommonCode.SUCCESS, previewUrl);
    }

    /**
     * 封装cmsPage数据
     * @param courseId
     * @return
     */
    private CmsPage getCmsPage(String courseId) {
        //查询mysql数据库course_base表获取课程信息
        CourseBase courseBase = this.findCourseBaseById(courseId);
        //发布课程预览页面
        CmsPage cmsPage = new CmsPage();
        //站点
        cmsPage.setSiteId(publish_siteId);//课程预览站点
        //模板
        cmsPage.setTemplateId(publish_templateId);
        //页面名称
        cmsPage.setPageName(courseId + ".html");
        //页面别名
        cmsPage.setPageAliase(courseBase.getName());
        //页面访问路径
        cmsPage.setPageWebPath(publish_page_webpath);
        //页面存储路径
        cmsPage.setPagePhysicalPath(publish_page_physicalpath);
        //数据url
        cmsPage.setDataUrl(publish_dataUrlPre + courseId);
        return cmsPage;
    }

    /**
     * 课程发布
     * @param courseId 课程主键id
     * @return
     */
    @Transactional
    public CoursePublishResult publish(String courseId) {
        // 封装cmsPage对象，保存到cms_page表中
        CmsPage cmsPage = this.getCmsPage(courseId);
        // 1. 调用cms服务的一键发布课程功能
        CmsPostPageResult cmsPostPageResult = cmsPageClient.postPageQuick(cmsPage);
        // 2. 修改课程状态为已发布  mysql 数据库 coursebase表
        this.saveCourseBase(courseId);
        // 3. 保存课程索引信息
            // 先创建一个coursePub对象
        CoursePub coursePub = this.getCoursePub(courseId);
            // 将coursePub的信息保存到数据库
        coursePubRepository.save(coursePub);
        // 4. 将课程计划相关的媒资信息保存到mysql的teachplan_media_pub表中,创建索引,用于视频播放页面查找
        this.saveTeachplanMediaPub(courseId);
        // 5. 响应结果
        //获取页面的访问路径
        String pageUrl = cmsPostPageResult.getPageUrl();
        return new CoursePublishResult(CommonCode.SUCCESS, pageUrl);
    }

    /**
     * 保存课程计划媒资信息到mysql的teachplan_media_pub表中,
     * 创建索引,用于视频播放页面查找
     *
     * @param courseId 课程id
     * @return
     */
    public void saveTeachplanMediaPub(String courseId) {
        // 1. 删除teachplan_media_pub表中的信息
        teachplanMediaPubRepository.deleteByCourseId(courseId);
        // 2. 查询teachplan_media表获取信息
        List<TeachplanMedia> teachplanMediaList = teachplanMediaRepository.findByCourseId(courseId);
        // 3. 将2中查出来的信息保存到teachplan_media_pub表中
        List<TeachplanMediaPub> teachplanMediaPubList = new ArrayList<TeachplanMediaPub>();
        for (TeachplanMedia teachplanMedia : teachplanMediaList) {
            TeachplanMediaPub teachplanMediaPub = new TeachplanMediaPub();
            BeanUtils.copyProperties(teachplanMedia, teachplanMediaPub);
            //设置teachplanMediaPub的时间戳
            teachplanMediaPub.setTimestamp(new Date());
            teachplanMediaPubList.add(teachplanMediaPub);
        }
        // 最后, 保存信息
        teachplanMediaPubRepository.saveAll(teachplanMediaPubList);
    }

    /**
     * 将课程信息统一封装到CoursePub对象中，用于创建索引
     * @param courseId
     * @return 封装课程所有信息的CoursePub对象
     */
    private CoursePub getCoursePub(String courseId) {
        CoursePub coursePub = new CoursePub();
        //1. 查询course_base表
        CourseBase courseBase = this.findById(courseId);
            //属性拷贝   形参(源, 目标)
        BeanUtils.copyProperties(courseBase, coursePub);
        //2. 查询course_pic表
        Optional<CoursePic> coursePicOptional = coursePicRepository.findById(courseId);
        if (coursePicOptional.isPresent()) {
            CoursePic coursePic = coursePicOptional.get();
            BeanUtils.copyProperties(coursePic, coursePub);
        }
        //3. 查询course_market表
        CourseMarket courseMarket = this.findCourseMarketByCourseId(courseId);
        BeanUtils.copyProperties(courseMarket, coursePub);
        //4. 查询teachplan表
        TeachplanNode teachplanNode = this.findTeachplanList(courseId);
        String teachPlan_str = JSON.toJSONString(teachplanNode);
        coursePub.setTeachplan(teachPlan_str);
        //5. 设置其他属性
            //Id
        coursePub.setId(courseId);
            //时间戳
        coursePub.setTimestamp(new Date());
            //设置发布时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String pubTime = simpleDateFormat.format(new Date());
        coursePub.setPubTime(pubTime);
        return coursePub;
    }


    /**
     * 修改mysql数据库中coursebase表
     * 将课程状态改为__已发布 "202002"
     * @param courseId
     * @return
     */
    private CourseBase saveCourseBase(String courseId) {
        CourseBase courseBase = this.findById(courseId);
        courseBase.setStatus("202002");
        return courseBaseRepository.save(courseBase);
    }

    /**
     * 保存课程计划和媒资信息的关联
     * @param teachplanMedia
     * @return
     */
    public ResponseResult saveTeachPlanAndMedia(TeachplanMedia teachplanMedia) {
        //获取课程计划的主键id
        String teachplanId = teachplanMedia.getTeachplanId();
        if (teachplanMedia == null || StringUtils.isEmpty(teachplanId)) {
            //前端参数无效
            ExceptionCast.cast(CommonCode.INVALID_PARAMS);
        }

        //1. 校验课程计划等级是否是3级
        Optional<Teachplan> teachplanOptional = teachplanRepository.findById(teachplanId);
        if (!teachplanOptional.isPresent()) {
            //课程计划不存在,抛出非法参数异常
            ExceptionCast.cast(CommonCode.INVALID_PARAMS);
        }
        Teachplan teachplan = teachplanOptional.get();
        if (!"3".equals(teachplan.getGrade())) {
            //课程计划等级不为 "3" , 抛出非法参数异常
            ExceptionCast.cast(CourseCode.COURSE_MEDIA_TEACHPLAN_GRADEERROR);
        }
        //2. 保存信息到teachplan_media数据库
        teachplanMediaRepository.save(teachplanMedia);

        return new ResponseResult(CommonCode.SUCCESS);

    }
}
